import React, { useRef, useEffect, useState, useCallback } from 'react'
import { Card, Button, Space, Typography } from 'antd'
import { PlayCircleOutlined, PauseCircleOutlined, ReloadOutlined } from '@ant-design/icons'
import { useWebSocket } from '../../hooks/useWebSocket'
import { Utils } from '../../utils'
import './PendulumCanvas.css'

const { Title, Text } = Typography

const PendulumCanvas = () => {
  const canvasRef = useRef(null)
  const ctxRef = useRef(null)
  const animationFrameRef = useRef(null)
  const lastDrawTimeRef = useRef(0)
  const frameCountRef = useRef(0)
  const lastFpsTimeRef = useRef(0)
  const animationStartTimeRef = useRef(0)
  
  const { pendulumState, sendKey, connected } = useWebSocket()
  
  // 单摆参数状态
  const [params, setParams] = useState({
    physicalLength: 100, // 摆长，单位cm
    displayScale: 2.5,   // 视觉增强比例
    angle: 5,            // 初始角度，单位度
    pivotX: 700,
    pivotY: 180,
    bobRadius: 24,
    angularVelocity: 0,
    angularAcceleration: 0,
    time: 0,
    running: false,
    periodCount: 0,
    lastPeriodTime: 0,
    periods: [],
    startTime: 0,
    maxAngularVelocity: 0,
    initialEnergy: 0,
    currentEnergy: 0
  })
  
  // 动画数据
  const [animationData, setAnimationData] = useState({
    angleHistory: [],
    positionHistory: []
  })
  
  // 摄像头同步数据
  const [cameraData, setCameraData] = useState({
    angle: 0,
    isSyncing: false,
    lastUpdateTime: 0
  })
  
  // 性能统计
  const [performance, setPerformance] = useState({
    fps: 0,
    latency: 0
  })
  
  // 运行状态
  const [runStatus, setRunStatus] = useState({
    running: false,
    text: '未运行'
  })

  const DRAW_INTERVAL = 16
  const MIN_UPDATE_INTERVAL = 8

  // 初始化画布
  const setupCanvas = useCallback(() => {
    const canvas = canvasRef.current
    if (!canvas) return
    
    const container = canvas.parentElement
    canvas.width = container.clientWidth * 1.5
    canvas.height = container.clientHeight * 1.5
    
    setParams(prev => ({
      ...prev,
      pivotX: canvas.width / 2
    }))
    
    ctxRef.current = canvas.getContext('2d')
    draw()
  }, [])

  // 绘制背景
  const drawBackground = useCallback(() => {
    const ctx = ctxRef.current
    const canvas = canvasRef.current
    if (!ctx || !canvas) return
    
    const w = canvas.width
    const h = canvas.height
    const gradient = ctx.createLinearGradient(0, 0, w, h)
    gradient.addColorStop(0, 'rgba(20, 30, 80, 0.4)')
    gradient.addColorStop(1, 'rgba(10, 20, 50, 0.8)')
    ctx.fillStyle = gradient
    ctx.fillRect(0, 0, w, h)
    
    // 绘制网格
    ctx.strokeStyle = 'rgba(100, 140, 255, 0.1)'
    ctx.lineWidth = 1
    for (let x = 0; x < w; x += 60) {
      ctx.beginPath()
      ctx.moveTo(x, 0)
      ctx.lineTo(x, h)
      ctx.stroke()
    }
    for (let y = 0; y < h; y += 60) {
      ctx.beginPath()
      ctx.moveTo(0, y)
      ctx.lineTo(w, y)
      ctx.stroke()
    }
  }, [])

  // 绘制刻度盘
  const drawDial = useCallback((angleRad) => {
    const ctx = ctxRef.current
    if (!ctx) return
    
    const dialRadius = 80
    ctx.beginPath()
    ctx.arc(params.pivotX, params.pivotY, dialRadius, 0, Math.PI * 2)
    ctx.strokeStyle = 'rgba(100, 180, 255, 0.4)'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 绘制刻度
    for (let i = -90; i <= 90; i += 10) {
      const rad = i * Math.PI / 180
      const x1 = params.pivotX + (dialRadius - 10) * Math.sin(rad)
      const y1 = params.pivotY + (dialRadius - 10) * Math.cos(rad)
      const x2 = params.pivotX + dialRadius * Math.sin(rad)
      const y2 = params.pivotY + dialRadius * Math.cos(rad)
      
      ctx.beginPath()
      ctx.moveTo(x1, y1)
      ctx.lineTo(x2, y2)
      ctx.strokeStyle = i % 30 === 0 ? 'rgba(255, 255, 255, 0.8)' : 'rgba(100, 180, 255, 0.6)'
      ctx.lineWidth = i % 30 === 0 ? 2 : 1
      ctx.stroke()
      
      if (i % 30 === 0) {
        ctx.font = '12px Arial'
        ctx.fillStyle = '#ffffff'
        ctx.textAlign = 'center'
        ctx.fillText(`${i}°`, params.pivotX + (dialRadius + 15) * Math.sin(rad), params.pivotY + (dialRadius + 15) * Math.cos(rad) + 4)
      }
    }
    
    // 绘制角度指示器
    const indicatorX = params.pivotX + (dialRadius + 25) * Math.sin(angleRad)
    const indicatorY = params.pivotY + (dialRadius + 25) * Math.cos(angleRad)
    ctx.beginPath()
    ctx.arc(indicatorX, indicatorY, 6, 0, Math.PI * 2)
    ctx.fillStyle = '#ff6b6b'
    ctx.fill()
  }, [params.pivotX, params.pivotY])

  // 绘制摆球
  const drawBob = useCallback((bobX, bobY) => {
    const ctx = ctxRef.current
    if (!ctx) return
    
    const gradient = ctx.createRadialGradient(
      bobX - 10, bobY - 10, params.bobRadius * 0.1,
      bobX, bobY, params.bobRadius
    )
    gradient.addColorStop(0, '#ffcc80')
    gradient.addColorStop(1, '#ffa726')
    
    ctx.beginPath()
    ctx.arc(bobX, bobY, params.bobRadius, 0, Math.PI * 2)
    ctx.fillStyle = gradient
    ctx.fill()
    
    // 摆球边框
    ctx.beginPath()
    ctx.arc(bobX, bobY, params.bobRadius, 0, Math.PI * 2)
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 摆球高光
    ctx.beginPath()
    ctx.arc(bobX - 8, bobY - 8, 6, 0, Math.PI * 2)
    ctx.fillStyle = 'rgba(255, 255, 255, 0.6)'
    ctx.fill()
  }, [params.bobRadius])

  // 主绘制函数
  const draw = useCallback(() => {
    const now = performance.now()
    if (now - lastDrawTimeRef.current < DRAW_INTERVAL) return
    lastDrawTimeRef.current = now
    
    const ctx = ctxRef.current
    const canvas = canvasRef.current
    if (!ctx || !canvas) return
    
    // 角度选择逻辑
    let angleToDraw = params.angle
    if (!params.running && cameraData.isSyncing) {
      angleToDraw = cameraData.angle
    }
    
    const angleRad = Utils.degToRad(angleToDraw)
    const displayLength = params.physicalLength * params.displayScale
    const bobX = params.pivotX + displayLength * Math.sin(angleRad)
    const bobY = params.pivotY + displayLength * Math.cos(angleRad)
    
    // 清除画布
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    
    // 绘制背景
    drawBackground()
    
    // 绘制单摆支架
    ctx.fillStyle = 'rgba(70, 90, 140, 0.8)'
    ctx.fillRect(params.pivotX - 100, params.pivotY - 40, 200, 40)
    
    // 绘制刻度盘
    drawDial(angleRad)
    
    // 绘制摆线
    ctx.beginPath()
    ctx.moveTo(params.pivotX, params.pivotY)
    ctx.lineTo(bobX, bobY)
    ctx.strokeStyle = 'rgba(240, 248, 255, 0.9)'
    ctx.lineWidth = 3
    ctx.stroke()
    
    // 绘制摆球
    drawBob(bobX, bobY)
    
    // 绘制信息文本
    if (!params.running) {
      ctx.font = '18px Arial'
      ctx.fillStyle = '#80deea'
      ctx.fillText(`当前角度: ${angleToDraw.toFixed(1)}°`, params.pivotX + 40, params.pivotY - 25)
    }
    
    // 绘制长度标记
    if (!params.running || Math.abs(angleToDraw) > 2) {
      ctx.beginPath()
      ctx.setLineDash([5, 5])
      ctx.moveTo(params.pivotX, params.pivotY)
      ctx.lineTo(params.pivotX, params.pivotY + displayLength)
      ctx.strokeStyle = 'rgba(100, 180, 255, 0.6)'
      ctx.lineWidth = 1
      ctx.stroke()
      ctx.setLineDash([])
      
      ctx.font = '16px Arial'
      ctx.fillStyle = '#80deea'
      ctx.fillText(`摆长: ${params.physicalLength.toFixed(1)} cm`, params.pivotX + 15, params.pivotY + displayLength / 2)
    }
    
    // 绘制摆轴位置信息
    if (!params.running) {
      ctx.font = '14px Arial'
      ctx.fillStyle = '#ffcc80'
      ctx.fillText(`摆轴: (${params.pivotX.toFixed(0)}, ${params.pivotY.toFixed(0)})`, 10, canvas.height - 30)
    }
  }, [params, cameraData, drawBackground, drawDial, drawBob])

  // 物理仿真
  const simulate = useCallback(() => {
    if (!params.running) return
    
    const currentTime = Date.now()
    const deltaTime = Math.min((currentTime - (params.startTime + params.time * 1000)) / 1000, 0.1)
    
    setParams(prev => {
      const newTime = prev.time + deltaTime
      const angleRad = Utils.degToRad(prev.angle)
      const physicalLengthM = prev.physicalLength / 100
      const gravity = 9.8
      const damping = 0.008
      
      const angularAcceleration = -(gravity * Math.sin(angleRad)) / physicalLengthM - damping * prev.angularVelocity
      const angularVelocity = prev.angularVelocity + angularAcceleration * deltaTime
      const angle = prev.angle + angularVelocity * deltaTime * 180 / Math.PI
      
      return {
        ...prev,
        time: newTime,
        angle,
        angularVelocity,
        angularAcceleration,
        maxAngularVelocity: Math.abs(angularVelocity) > Math.abs(prev.maxAngularVelocity) ? angularVelocity : prev.maxAngularVelocity
      }
    })
    
    // 记录动画数据
    const now = Date.now()
    const timeFromStart = (now - animationStartTimeRef.current) / 1000
    const angleRad = Utils.degToRad(params.angle)
    const displayLength = params.physicalLength * params.displayScale
    const bobX = params.pivotX + displayLength * Math.sin(angleRad)
    const bobY = params.pivotY + displayLength * Math.cos(angleRad)
    
    setAnimationData(prev => {
      const newAngleHistory = [...prev.angleHistory, { time: timeFromStart, angle: params.angle }]
      const newPositionHistory = [...prev.positionHistory, { 
        time: timeFromStart, 
        x: bobX - params.pivotX, 
        y: bobY - params.pivotY 
      }]
      
      return {
        angleHistory: newAngleHistory.slice(-1000), // 保持最近1000个点
        positionHistory: newPositionHistory.slice(-1000)
      }
    })
    
    // 更新性能统计
    frameCountRef.current++
    
    // 绘制
    draw()
    
    // 继续动画
    animationFrameRef.current = requestAnimationFrame(simulate)
  }, [params, draw])

  // 开始/暂停实验
  const toggleStart = useCallback(() => {
    if (!params.running) {
      // 开始实验
      setParams(prev => ({
        ...prev,
        running: true,
        time: 0,
        angularVelocity: 0,
        periodCount: 0,
        periods: [],
        startTime: Date.now(),
        maxAngularVelocity: 0
      }))
      
      setRunStatus({
        running: true,
        text: '正在运行'
      })
      
      animationStartTimeRef.current = Date.now()
      
      // 发送d0信号
      if (connected && sendKey) {
        sendKey('d0')
        console.log('开始实验，发送d0信号')
      }
      
      // 开始仿真
      simulate()
    } else {
      // 暂停实验
      setParams(prev => ({
        ...prev,
        running: false
      }))
      
      setRunStatus({
        running: false,
        text: '未运行'
      })
      
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current)
      }
    }
  }, [params.running, connected, sendKey, simulate])

  // 重置实验
  const reset = useCallback(() => {
    // 停止动画
    if (animationFrameRef.current) {
      cancelAnimationFrame(animationFrameRef.current)
    }
    
    setParams(prev => ({
      ...prev,
      angle: 5,
      angularVelocity: 0,
      angularAcceleration: 0,
      time: 0,
      running: false,
      periodCount: 0,
      periods: [],
      startTime: 0,
      maxAngularVelocity: 0,
      initialEnergy: 0,
      currentEnergy: 0
    }))
    
    setRunStatus({
      running: false,
      text: '未运行'
    })
    
    setAnimationData({
      angleHistory: [],
      positionHistory: []
    })
    
    animationStartTimeRef.current = performance.now()
    
    // 重绘
    draw()
    
    Utils.showToast('实验已重置', 'success')
  }, [draw])

  // 处理WebSocket数据更新
  useEffect(() => {
    if (pendulumState) {
      // 更新摄像头同步数据
      if (pendulumState.angle !== undefined && !params.running) {
        setCameraData(prev => ({
          ...prev,
          angle: pendulumState.angle,
          isSyncing: true,
          lastUpdateTime: Date.now()
        }))
      }
      
      // 更新摆长
      if (pendulumState.length !== undefined) {
        setParams(prev => ({
          ...prev,
          physicalLength: pendulumState.length
        }))
      }
    }
  }, [pendulumState, params.running])

  // 初始化
  useEffect(() => {
    setupCanvas()
    
    const handleResize = () => {
      setupCanvas()
    }
    
    window.addEventListener('resize', handleResize)
    
    return () => {
      window.removeEventListener('resize', handleResize)
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current)
      }
    }
  }, [setupCanvas])

  // 性能统计更新
  useEffect(() => {
    const interval = setInterval(() => {
      const now = performance.now()
      if (now - lastFpsTimeRef.current >= 1000) {
        setPerformance(prev => ({
          ...prev,
          fps: frameCountRef.current
        }))
        frameCountRef.current = 0
        lastFpsTimeRef.current = now
      }
    }, 1000)
    
    return () => clearInterval(interval)
  }, [])

  return (
    <Card 
      title="单摆动画"
      className="pendulum-canvas-card"
      extra={
        <div className="status-indicator">
          <span className={`status-dot ${runStatus.running ? 'running' : 'not-running'}`}></span>
          <span className="status-text">{runStatus.text}</span>
        </div>
      }
    >
      <div className="canvas-container">
        <div className="timer-display">
          实验时间: <span className="timer-value">{Utils.formatTime(params.time)}</span> 秒
        </div>
        <canvas 
          ref={canvasRef}
          className="pendulum-canvas"
          width={1400} 
          height={1000}
        />
        <div className="control-buttons">
          <Space>
            <Button 
              type="primary" 
              icon={params.running ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
              onClick={toggleStart}
              size="large"
            >
              {params.running ? '暂停实验' : '开始实验'}
            </Button>
            <Button 
              icon={<ReloadOutlined />}
              onClick={reset}
              size="large"
            >
              重置实验
            </Button>
          </Space>
        </div>
        <div className="quick-instructions">
          <div className="instructions-title">快捷操作说明</div>
          <div className="instructions-list">
            <div className="instruction-item">左键: 设定摆心</div>
            <div className="instruction-item">右键: 设定坐标轴零点</div>
            <div className="instruction-item">r: 设置角度零点</div>
            <div className="instruction-item">p: 输出最近10条数据</div>
            <div className="instruction-item">c: 校准HSV识别</div>
            <div className="instruction-item">d: 删除参考点和参考角度</div>
            <div className="instruction-item">l: 启动/终止串口通信</div>
            <div className="instruction-item">x: 导出数据为json</div>
          </div>
        </div>
      </div>
    </Card>
  )
}

export default PendulumCanvas
